package com.fredia.terp.exception;

import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.internal.engine.ConstraintViolationImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import com.fredia.terp.util.ResultCodes;
import com.fredia.terp.util.json.JsonRender;
import com.fredia.terp.util.json.JsonResult;
import com.fredia.terp.util.json.JsonUtils;

/**
 * 异常处理 托管给spring
 * 
 * @author : wangyong
 * @since : 2017年6月27日
 * @version : v0.0.1
 */

public class ExceptionHandler implements HandlerExceptionResolver {

	private static final Logger logger = LoggerFactory.getLogger(ExceptionHandler.class);

	private String msg = "系统繁忙,请稍后再试";

	/* 异常信息地址 */
	private String errorUrl = "errorUrl";
	/* 权限异常地址 */
	private String unauthorizedUrl;
	/* 异常信息获取对象名称 */
	private String errorName = "errorName";
	/* 是否将异常信息抛出 这里主要是将信息抛出到页面 默认关闭 */
	private boolean exceptionSwitch = false;

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public String getErrorUrl() {
		return errorUrl;
	}

	public void setErrorUrl(String errorUrl) {
		this.errorUrl = errorUrl;
	}

	public String getUnauthorizedUrl() {
		return unauthorizedUrl;
	}

	public void setUnauthorizedUrl(String unauthorizedUrl) {
		this.unauthorizedUrl = unauthorizedUrl;
	}

	public String getErrorName() {
		return errorName;
	}

	public void setErrorName(String errorName) {
		this.errorName = errorName;
	}

	public boolean isExceptionSwitch() {
		return exceptionSwitch;
	}

	public void setExceptionSwitch(boolean exceptionSwitch) {
		this.exceptionSwitch = exceptionSwitch;
	}

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {
		logger.error("自定义异常：" + ex.getMessage(), ex);
		String errorMsg = "";

		errorMsg = hibernateValidator(ex, errorMsg);
		errorMsg = BaseExceptionValidator(ex, errorMsg);
		errorMsg = ServiceExceptionValidator(ex, errorMsg);
		errorMsg = UnauthorizedException(ex, errorMsg);
		if (StringUtils.isEmpty(errorMsg)) {
			errorMsg = msg;
		}

		if (JsonUtils.isAjax(handler)) {
			try {
				JsonResult result = new JsonResult(ResultCodes.ERROR, errorMsg);
				JsonRender render = new JsonRender(result);
				render.render();
			} catch (RenderException e) {
			}
			return new ModelAndView();
		}

		// 权限异常跳转到权限异常信息页面
		if (ex instanceof org.apache.shiro.authz.UnauthorizedException) {
			return new ModelAndView(unauthorizedUrl);
		}

		ModelAndView view = new ModelAndView("redirect:" + errorUrl); // 关于异常拦截页面异常跳转的地址后期配置为动态
		if (exceptionSwitch) {
			view.addObject(errorName, errorMsg); // 将异常消息抛出
		}
		return view;
	}

	/**
	 * hibernateValidator数据验证异常
	 * 
	 * @param ex
	 * @param errorMsg
	 * @return
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	@SuppressWarnings("rawtypes")
	public String hibernateValidator(Exception ex, String errorMsg) {
		if (StringUtils.isNotEmpty(errorMsg)) {
			return errorMsg;
		}

		if (ex instanceof ConstraintViolationsException) {
			Set constraintViolations = (Set) ((ConstraintViolationsException) ex).getObject();
			Object[] objects = constraintViolations.toArray();
			ConstraintViolationImpl constraintViolationImpl = null;
			if (objects != null) {
				constraintViolationImpl = (ConstraintViolationImpl) objects[0];
			}
			if (constraintViolationImpl != null) {
				return constraintViolationImpl.getMessageTemplate();
			}
		}
		return errorMsg;
	}

	/**
	 * 基类异常
	 * 
	 * @param ex
	 * @param errorMsg
	 * @return
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	public String BaseExceptionValidator(Exception ex, String errorMsg) {
		if (StringUtils.isNotEmpty(errorMsg)) {
			return errorMsg;
		}

		if (ex instanceof BaseException) {
			return ex.getMessage();
		}
		return errorMsg;
	}

	/**
	 * 业务异常
	 * 
	 * @param ex
	 * @param errorMsg
	 * @return
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	public String ServiceExceptionValidator(Exception ex, String errorMsg) {
		if (StringUtils.isNotEmpty(errorMsg)) {
			return errorMsg;
		}

		if (ex instanceof ServiceException) {
			return ex.getMessage();
		}
		return errorMsg;
	}

	/**
	 * 权限异常 这里托管里shiro 的权限异常 针对后台管理员系统
	 * 
	 * @param ex
	 * @param errorMsg
	 * @return
	 * @author : wangyong
	 * @since : 2017年6月27日
	 */
	public String UnauthorizedException(Exception ex, String errorMsg) {
		if (StringUtils.isNotEmpty(errorMsg)) {
			return errorMsg;
		}
		if (ex instanceof org.apache.shiro.authz.UnauthorizedException) {
			return "操作权限异常";
		}
		return errorMsg;
	}
}
